package cn.zfgc.zface.service.impl;

import java.io.ByteArrayInputStream;
import java.rmi.RemoteException;
import java.util.Date;

import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axis.client.Call;
import org.apache.axis.encoding.XMLType;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;
import org.apache.axis2.transport.http.HTTPConstants;
import org.springframework.stereotype.Service;

import cn.zfgc.base.api.DateTimeUtils;
import cn.zfgc.base.api.Exceptions;
import cn.zfgc.base.api.StringUtils;
import cn.zfgc.base.api.time.constant.DateTimeFormat;
import cn.zfgc.zface.model.ErrorLog;
import cn.zfgc.zface.model.Zface;
import cn.zfgc.zface.service.WebServicesService;
import lombok.extern.slf4j.Slf4j;

/**
 * @author caoyuan on 2017/10/11.
 */
@Slf4j
@Service
public class WebServiceServiceImpl implements WebServicesService {

    /**
     * 将xml 文本 转换为xml对象 .
     *
     * @param xmlStr xml文本
     * @return xml对象
     */
    private static OMElement str2OMElement(final String xmlStr) {
        OMElement xmlValue;
        try {
            xmlValue = new StAXOMBuilder(new ByteArrayInputStream(xmlStr.getBytes("UTF-8"))).getDocumentElement();
            return xmlValue;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String doJson(Zface inter, String data) {
        String obj = null;
        try {
            org.apache.axis.client.Service service = new org.apache.axis.client.Service();
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(inter.getStr("zfaceUrl"));
            call.setOperationName(inter.getStr("webServicesMethod"));
            call.setTimeout(Integer.valueOf(inter.getInt("soTimeout")));
            if (StringUtils.isNotBlank(inter.getStr("arrayParaName"))) {
                call.addParameter(inter.getStr("arrayParaName"), XMLType.XSD_ANYTYPE, ParameterMode.IN);
                call.setReturnClass(String.class);
            }
            obj = (String) call.invoke(new Object[]{data });
        } catch (ServiceException e) {
            new ErrorLog().set("faceKey", inter.getStr("faceKey")).set("zfaceName", inter.getStr("zfaceName"))
                    .set("errorTime", DateTimeUtils.date2Str(new Date(), DateTimeFormat.Format2)).set("errorMsg", Exceptions.getStackTraceAsString(e)).save();
            log.error("", e);
        } catch (RemoteException e) {
            new ErrorLog().set("faceKey", inter.getStr("faceKey")).set("zfaceName", inter.getStr("zfaceName"))
                    .set("errorTime", DateTimeUtils.date2Str(new Date(), DateTimeFormat.Format2)).set("errorMsg", Exceptions.getStackTraceAsString(e)).save();
            log.error("", e);
        }

        return String.valueOf(obj);
    }

    @Override
    public String doXml(Zface inter, String data) {
        String returnXML = "";
        try {
            RPCServiceClient serviceClient = new RPCServiceClient();
            Options options = serviceClient.getOptions();
            options.setAction("");
            options.setProperty(HTTPConstants.CHUNKED, false);
            options.setProperty(HTTPConstants.CONNECTION_TIMEOUT, inter.getInt("connectTimeout"));
            options.setProperty(HTTPConstants.SO_TIMEOUT, inter.getInt("soTimeout"));
            options.setProperty(org.apache.axis2.Constants.Configuration.DISABLE_SOAP_ACTION, true);
            options.setExceptionToBeThrownOnSOAPFault(true);
            options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
            EndpointReference targetEPR = new EndpointReference(inter.getStr("zfaceUrl"));
            options.setTo(targetEPR);
            OMFactory fac = OMAbstractFactory.getOMFactory();

            OMNamespace omNs = fac.createOMNamespace(inter.getStr("webServicesNamespace"), null);
            OMElement method = fac.createOMElement(inter.getStr("webServicesMethod"), omNs);
            method.addChild(str2OMElement(data));

            returnXML = serviceClient.sendReceive(method).getFirstElement().getText();
            serviceClient.cleanupTransport();

        } catch (RemoteException e) {
            new ErrorLog().set("faceKey", inter.getStr("faceKey")).set("zfaceName", inter.getStr("zfaceName"))
                    .set("errorTime", DateTimeUtils.date2Str(new Date(), DateTimeFormat.Format2)).set("errorMsg", Exceptions.getStackTraceAsString(e)).save();
            log.error("", e);
        }

        return returnXML;
    }

    @Override
    public String doArray(Zface inter, String data) {
        Object obj = null;
        try {
            org.apache.axis.client.Service service = new org.apache.axis.client.Service();
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(inter.getStr("zfaceUrl"));
            // 设置要调用的方法的名字
            call.setOperationName(inter.getStr("webServicesMethod"));
            call.setTimeout(Integer.valueOf(inter.getInt("soTimeout")));
            if (StringUtils.isNotBlank(inter.getStr("arrayParaName"))) {
                call.addParameter(inter.getStr("arrayParaName"), XMLType.XSD_ANYTYPE, ParameterMode.IN);
                call.setReturnClass(String.class);
            }

            String[] array = new String[]{data };
            obj = call.invoke(new Object[]{array });
        } catch (RemoteException e) {
            new ErrorLog().set("faceKey", inter.getStr("faceKey")).set("zfaceName", inter.getStr("zfaceName"))
                    .set("errorTime", DateTimeUtils.date2Str(new Date(), DateTimeFormat.Format2)).set("errorMsg", Exceptions.getStackTraceAsString(e)).save();
            log.error("", e);
        } catch (ServiceException e) {
            new ErrorLog().set("faceKey", inter.getStr("faceKey")).set("zfaceName", inter.getStr("zfaceName"))
                    .set("errorTime", DateTimeUtils.date2Str(new Date(), DateTimeFormat.Format2)).set("errorMsg", Exceptions.getStackTraceAsString(e)).save();
            log.error("", e);
        }
        return String.valueOf(obj);
    }
}
